home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / Source / Chapter 6 / Engine / DeviceEnumeration.cpp next >
Encoding:
C/C++ Source or Header  |  2004-10-01  |  17.4 KB  |  436 lines

  1. //-----------------------------------------------------------------------------
  2. // DeviceEnumeration.h implementation.
  3. // Refer to the DeviceEnumeration.h interface for more details.
  4. //
  5. // Programming a Multiplayer First Person Shooter in DirectX
  6. // Copyright (c) 2004 Vaughan Young
  7. //-----------------------------------------------------------------------------
  8. #include "Engine.h"
  9.  
  10. //-----------------------------------------------------------------------------
  11. // Globals
  12. //-----------------------------------------------------------------------------
  13. DeviceEnumeration *g_deviceEnumeration = NULL;
  14.  
  15. //-----------------------------------------------------------------------------
  16. // A callback director for the graphics settings dialog's message handler.
  17. //-----------------------------------------------------------------------------
  18. BOOL CALLBACK SettingsDialogProcDirector( HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam )
  19. {
  20.     return g_deviceEnumeration->SettingsDialogProc( hDlg, uiMsg, wParam, lParam );
  21. }
  22.  
  23. //-----------------------------------------------------------------------------
  24. // Enumerates available Direct3D devices on the default adapter.
  25. //-----------------------------------------------------------------------------
  26. INT_PTR DeviceEnumeration::Enumerate( IDirect3D9 *d3d )
  27. {
  28.     // Create the display modes linked list.
  29.     m_displayModes = new LinkedList< DisplayMode >;
  30.  
  31.     // Load the settings script.
  32.     m_settingsScript = new Script( "DisplaySettings.txt" );
  33.  
  34.     // Get the details of the default adapter.
  35.     d3d->GetAdapterIdentifier( D3DADAPTER_DEFAULT, 0, &m_adapter );
  36.  
  37.     // Build a list of the allowable pixel formats.
  38.     D3DFORMAT allowedFormats[6];
  39.     allowedFormats[0] = D3DFMT_X1R5G5B5;
  40.     allowedFormats[1] = D3DFMT_A1R5G5B5;
  41.     allowedFormats[2] = D3DFMT_R5G6B5;
  42.     allowedFormats[3] = D3DFMT_X8R8G8B8;
  43.     allowedFormats[4] = D3DFMT_A8R8G8B8;
  44.     allowedFormats[5] = D3DFMT_A2R10G10B10;
  45.  
  46.     // Go through the list of allowable pixel formats.
  47.     for( char af = 0; af < 6; af++ )
  48.     {
  49.         // Get the number of adapter modes and go through them.
  50.         unsigned long totalAdapterModes = d3d->GetAdapterModeCount( D3DADAPTER_DEFAULT, allowedFormats[af] );
  51.         for( unsigned long m = 0; m < totalAdapterModes; m++ )
  52.         {
  53.             // Get the display mode details.
  54.             D3DDISPLAYMODE mode;
  55.             d3d->EnumAdapterModes( D3DADAPTER_DEFAULT, allowedFormats[af], m, &mode );
  56.  
  57.             // Reject small display modes.
  58.             if( mode.Height < 480 )
  59.                 continue;
  60.  
  61.             // Create the new display mode.
  62.             DisplayMode *displayMode = new DisplayMode;
  63.             memcpy( &displayMode->mode, &mode, sizeof( D3DDISPLAYMODE ) );
  64.             if( af < 3 )
  65.                 strcpy( displayMode->bpp, "16 bpp" );
  66.             else
  67.                 strcpy( displayMode->bpp, "32 bpp" );
  68.  
  69.             // Add this display mode to the list.
  70.             m_displayModes->Add( displayMode );
  71.         }
  72.     }
  73.  
  74.     return DialogBox( NULL, MAKEINTRESOURCE( IDD_GRAPHICS_SETTINGS ), NULL, SettingsDialogProcDirector );
  75. }
  76.  
  77. //-----------------------------------------------------------------------------
  78. // Handles window messages for the graphics settings dialog.
  79. //-----------------------------------------------------------------------------
  80. INT_PTR DeviceEnumeration::SettingsDialogProc( HWND dialog, UINT msg, WPARAM wparam, LPARAM lparam )
  81. {
  82.     switch( msg )
  83.     {
  84.         case WM_INITDIALOG:
  85.         {
  86.             // Display the adapter details and its driver version.
  87.             char version[16];
  88.             sprintf( version, "%d", LOWORD( m_adapter.DriverVersion.LowPart ) );
  89.             Edit_SetText( GetDlgItem( dialog, IDC_DISPLAY_ADAPTER ), m_adapter.Description );
  90.             Edit_SetText( GetDlgItem( dialog, IDC_DRIVER_VERSION ), version );
  91.  
  92.             // Check if the settings script has anything in it.
  93.             if( m_settingsScript->GetBoolData( "windowed" ) == NULL )
  94.             {
  95.                 // The settings script is empty, so default to windowed mode.
  96.                 CheckDlgButton( dialog, IDC_WINDOWED, m_windowed = true );
  97.             }
  98.             else
  99.             {
  100.                 // Load the window mode state.
  101.                 CheckDlgButton( dialog, IDC_WINDOWED, m_windowed = *m_settingsScript->GetBoolData( "windowed" ) );
  102.                 CheckDlgButton( dialog, IDC_FULLSCREEN, !m_windowed );
  103.  
  104.                 // Check if running in fullscreen mode.
  105.                 if( m_windowed == false )
  106.                 {
  107.                     // Enable all the fullscreen controls.
  108.                     EnableWindow( GetDlgItem( dialog, IDC_VSYNC ), true );
  109.                     EnableWindow( GetDlgItem( dialog, IDC_DISPLAY_FORMAT ), true );
  110.                     EnableWindow( GetDlgItem( dialog, IDC_RESOLUTION ), true );
  111.                     EnableWindow( GetDlgItem( dialog, IDC_REFRESH_RATE ), true );
  112.  
  113.                     // Load the vsync state.
  114.                     CheckDlgButton( dialog, IDC_VSYNC, m_vsync = *m_settingsScript->GetBoolData( "vsync" ) );
  115.  
  116.                     // Fill in the display formats combo box.
  117.                     ComboBox_ResetContent( GetDlgItem( dialog, IDC_DISPLAY_FORMAT ) );
  118.                     m_displayModes->Iterate( true );
  119.                     while( m_displayModes->Iterate() )
  120.                         if( !ComboBoxContainsText( dialog, IDC_DISPLAY_FORMAT, m_displayModes->GetCurrent()->bpp ) )
  121.                             ComboBoxAdd( dialog, IDC_DISPLAY_FORMAT, (void*)m_displayModes->GetCurrent()->mode.Format, m_displayModes->GetCurrent()->bpp );
  122.                     ComboBoxSelect( dialog, IDC_DISPLAY_FORMAT, *m_settingsScript->GetNumberData( "bpp" ) );
  123.  
  124.                     char text[16];
  125.  
  126.                     // Fill in the resolutions combo box.
  127.                     ComboBox_ResetContent( GetDlgItem( dialog, IDC_RESOLUTION ) );
  128.                     m_displayModes->Iterate( true );
  129.                     while( m_displayModes->Iterate() )
  130.                     {
  131.                         if( m_displayModes->GetCurrent()->mode.Format == (D3DFORMAT)PtrToUlong( ComboBoxSelected( dialog, IDC_COLOUR_DEPTH ) ) )
  132.                         {
  133.                             sprintf( text, "%d x %d", m_displayModes->GetCurrent()->mode.Width, m_displayModes->GetCurrent()->mode.Height );
  134.                             if (!ComboBoxContainsText( dialog, IDC_RESOLUTION, text ) )
  135.                                 ComboBoxAdd( dialog, IDC_RESOLUTION, (void*)MAKELONG( m_displayModes->GetCurrent()->mode.Width, m_displayModes->GetCurrent()->mode.Height ), text );
  136.                         }
  137.                     }
  138.                     ComboBoxSelect( dialog, IDC_RESOLUTION, *m_settingsScript->GetNumberData( "resolution" ) );
  139.  
  140.                     // Fill in the refresh rates combo box.
  141.                     ComboBox_ResetContent( GetDlgItem( dialog, IDC_REFRESH_RATE ) );
  142.                     m_displayModes->Iterate( true );
  143.                     while( m_displayModes->Iterate() )
  144.                     {
  145.                         if( (DWORD)MAKELONG( m_displayModes->GetCurrent()->mode.Width, m_displayModes->GetCurrent()->mode.Height ) == (DWORD)PtrToUlong( ComboBoxSelected( dialog, IDC_RESOLUTION ) ) )
  146.                         {
  147.                             sprintf( text, "%d Hz", m_displayModes->GetCurrent()->mode.RefreshRate );
  148.                             if (!ComboBoxContainsText( dialog, IDC_REFRESH_RATE, text ) )
  149.                                 ComboBoxAdd( dialog, IDC_REFRESH_RATE, (void*)m_displayModes->GetCurrent()->mode.RefreshRate, text );
  150.                         }
  151.                     }
  152.                     ComboBoxSelect( dialog, IDC_REFRESH_RATE, *m_settingsScript->GetNumberData( "refresh" ) );
  153.                 }
  154.             }
  155.  
  156.             return true;
  157.         }
  158.  
  159.         case WM_COMMAND:
  160.         {
  161.             switch( LOWORD(wparam) )
  162.             {
  163.                 case IDOK:
  164.                 {
  165.                     // Store the details of the selected display mode.
  166.                     m_selectedDisplayMode.Width = LOWORD( PtrToUlong( ComboBoxSelected( dialog, IDC_RESOLUTION ) ) );
  167.                     m_selectedDisplayMode.Height = HIWORD( PtrToUlong( ComboBoxSelected( dialog, IDC_RESOLUTION ) ) );
  168.                     m_selectedDisplayMode.RefreshRate = PtrToUlong( ComboBoxSelected( dialog, IDC_REFRESH_RATE ) );
  169.                     m_selectedDisplayMode.Format = (D3DFORMAT)PtrToUlong( ComboBoxSelected( dialog, IDC_DISPLAY_FORMAT ) );
  170.                     m_windowed = IsDlgButtonChecked( dialog, IDC_WINDOWED ) ? true : false;
  171.                     m_vsync = IsDlgButtonChecked( dialog, IDC_VSYNC ) ? true : false;
  172.  
  173.                     // Destroy the display modes list.
  174.                     SAFE_DELETE( m_displayModes );
  175.  
  176.                     // Get the selected index from each combo box.
  177.                     long bpp = ComboBox_GetCurSel( GetDlgItem( dialog, IDC_DISPLAY_FORMAT ) );
  178.                     long resolution = ComboBox_GetCurSel( GetDlgItem( dialog, IDC_RESOLUTION ) );
  179.                     long refresh = ComboBox_GetCurSel( GetDlgItem( dialog, IDC_REFRESH_RATE ) );
  180.  
  181.                     // Check if the settings script has anything in it.
  182.                     if( m_settingsScript->GetBoolData( "windowed" ) == NULL )
  183.                     {
  184.                         // Add all the settings to the script.
  185.                         m_settingsScript->AddVariable( "windowed", VARIABLE_BOOL, &m_windowed );
  186.                         m_settingsScript->AddVariable( "vsync", VARIABLE_BOOL, &m_vsync );
  187.                         m_settingsScript->AddVariable( "bpp", VARIABLE_NUMBER, &bpp );
  188.                         m_settingsScript->AddVariable( "resolution", VARIABLE_NUMBER, &resolution );
  189.                         m_settingsScript->AddVariable( "refresh", VARIABLE_NUMBER, &refresh );
  190.                     }
  191.                     else
  192.                     {
  193.                         // Set all the settings.
  194.                         m_settingsScript->SetVariable( "windowed", &m_windowed );
  195.                         m_settingsScript->SetVariable( "vsync", &m_vsync );
  196.                         m_settingsScript->SetVariable( "bpp", &bpp );
  197.                         m_settingsScript->SetVariable( "resolution", &resolution );
  198.                         m_settingsScript->SetVariable( "refresh", &refresh );
  199.                     }
  200.  
  201.                     // Save all the settings out to the settings script.
  202.                     m_settingsScript->SaveScript();
  203.  
  204.                     // Destroy the settings script.
  205.                     SAFE_DELETE( m_settingsScript );
  206.  
  207.                     // Close the dialog.
  208.                     EndDialog( dialog, IDOK );
  209.  
  210.                     return true;
  211.                 }
  212.  
  213.                 case IDCANCEL:
  214.                 {
  215.                     // Destroy the display modes list.
  216.                     SAFE_DELETE( m_displayModes );
  217.  
  218.                     // Destroy the settings script.
  219.                     SAFE_DELETE( m_settingsScript );
  220.  
  221.                     EndDialog( dialog, IDCANCEL );
  222.  
  223.                     return true;
  224.                 }
  225.  
  226.                 case IDC_COLOUR_DEPTH:
  227.                 {
  228.                     if( CBN_SELCHANGE == HIWORD(wparam) )
  229.                     {
  230.                         char res[16];
  231.                         DWORD selectedRes = (DWORD)PtrToUlong( ComboBoxSelected( dialog, IDC_RESOLUTION ) );
  232.  
  233.                         // Update the resolution combo box.
  234.                         ComboBox_ResetContent( GetDlgItem( dialog, IDC_RESOLUTION ) );
  235.                         m_displayModes->Iterate( true );
  236.                         while( m_displayModes->Iterate() )
  237.                         {
  238.                             if( m_displayModes->GetCurrent()->mode.Format == (D3DFORMAT)PtrToUlong( ComboBoxSelected( dialog, IDC_COLOUR_DEPTH ) ) )
  239.                             {
  240.                                 sprintf( res, "%d x %d", m_displayModes->GetCurrent()->mode.Width, m_displayModes->GetCurrent()->mode.Height );
  241.                                 if( !ComboBoxContainsText( dialog, IDC_RESOLUTION, res ) )
  242.                                 {
  243.                                     ComboBoxAdd( dialog, IDC_RESOLUTION, (void*)MAKELONG( m_displayModes->GetCurrent()->mode.Width, m_displayModes->GetCurrent()->mode.Height ), res );
  244.                                     if( selectedRes == (DWORD)MAKELONG( m_displayModes->GetCurrent()->mode.Width, m_displayModes->GetCurrent()->mode.Height ) )
  245.                                         ComboBoxSelect( dialog, IDC_RESOLUTION, (void*)selectedRes );
  246.                                 }
  247.                             }
  248.                         }
  249.                         if( ComboBoxSelected( dialog, IDC_RESOLUTION ) == NULL )
  250.                             ComboBoxSelect( dialog, IDC_RESOLUTION, 0 );
  251.                     }
  252.  
  253.                     return true;
  254.                 }
  255.  
  256.                 case IDC_RESOLUTION:
  257.                 {
  258.                     if( CBN_SELCHANGE == HIWORD(wparam) )
  259.                     {
  260.                         char refresh[16];
  261.                         DWORD selectedRefresh = (DWORD)PtrToUlong( ComboBoxSelected( dialog, IDC_REFRESH_RATE ) );
  262.  
  263.                         // Update the refresh rate combo box.
  264.                         ComboBox_ResetContent( GetDlgItem( dialog, IDC_REFRESH_RATE ) );
  265.                         m_displayModes->Iterate( true );
  266.                         while( m_displayModes->Iterate() )
  267.                         {
  268.                             if( (DWORD)MAKELONG( m_displayModes->GetCurrent()->mode.Width, m_displayModes->GetCurrent()->mode.Height ) == (DWORD)PtrToUlong( ComboBoxSelected( dialog, IDC_RESOLUTION ) ) )
  269.                             {
  270.                                 sprintf( refresh, "%d Hz", m_displayModes->GetCurrent()->mode.RefreshRate );
  271.                                 if( !ComboBoxContainsText( dialog, IDC_REFRESH_RATE, refresh ) )
  272.                                 {
  273.                                     ComboBoxAdd( dialog, IDC_REFRESH_RATE, (void*)m_displayModes->GetCurrent()->mode.RefreshRate, refresh );
  274.                                     if( selectedRefresh == m_displayModes->GetCurrent()->mode.RefreshRate )
  275.                                         ComboBoxSelect( dialog, IDC_REFRESH_RATE, (void*)selectedRefresh );
  276.                                 }
  277.                             }
  278.                         }
  279.                         if( ComboBoxSelected( dialog, IDC_REFRESH_RATE ) == NULL )
  280.                             ComboBoxSelect( dialog, IDC_REFRESH_RATE, 0 );
  281.                     }
  282.  
  283.                     return true;
  284.                 }
  285.  
  286.                 case IDC_WINDOWED:
  287.                 case IDC_FULLSCREEN:
  288.                 {
  289.                     // Check if the user has change to windowed or fullscreen mode.
  290.                     if( IsDlgButtonChecked( dialog, IDC_WINDOWED ) )
  291.                     {
  292.                         // Clear and disable all the fullscreen controls.
  293.                         ComboBox_ResetContent( GetDlgItem( dialog, IDC_DISPLAY_FORMAT ) );
  294.                         ComboBox_ResetContent( GetDlgItem( dialog, IDC_RESOLUTION ) );
  295.                         ComboBox_ResetContent( GetDlgItem( dialog, IDC_REFRESH_RATE ) );
  296.                         CheckDlgButton( dialog, IDC_VSYNC, false );
  297.                         EnableWindow( GetDlgItem( dialog, IDC_VSYNC ), false );
  298.                         EnableWindow( GetDlgItem( dialog, IDC_DISPLAY_FORMAT ), false );
  299.                         EnableWindow( GetDlgItem( dialog, IDC_RESOLUTION ), false );
  300.                         EnableWindow( GetDlgItem( dialog, IDC_REFRESH_RATE ), false );
  301.                     }
  302.                     else
  303.                     {
  304.                         // Enable all the fullscreen controls.
  305.                         EnableWindow( GetDlgItem( dialog, IDC_VSYNC ), true );
  306.                         EnableWindow( GetDlgItem( dialog, IDC_DISPLAY_FORMAT ), true );
  307.                         EnableWindow( GetDlgItem( dialog, IDC_RESOLUTION ), true );
  308.                         EnableWindow( GetDlgItem( dialog, IDC_REFRESH_RATE ), true );
  309.  
  310.                         // Fill in the display formats combo box.
  311.                         ComboBox_ResetContent( GetDlgItem( dialog, IDC_DISPLAY_FORMAT ) );
  312.                         m_displayModes->Iterate( true );
  313.                         while( m_displayModes->Iterate() )
  314.                         {
  315.                             if( !ComboBoxContainsText( dialog, IDC_DISPLAY_FORMAT, m_displayModes->GetCurrent()->bpp ) )
  316.                                 ComboBoxAdd( dialog, IDC_DISPLAY_FORMAT, (void*)m_displayModes->GetCurrent()->mode.Format, m_displayModes->GetCurrent()->bpp );
  317.                         }
  318.                         ComboBoxSelect( dialog, IDC_DISPLAY_FORMAT, 0 );
  319.                     }
  320.  
  321.                     return true;
  322.                 }
  323.             }
  324.         }
  325.     }
  326.  
  327.     return false;
  328. }
  329.  
  330. //-----------------------------------------------------------------------------
  331. // Returns the selected display mode.
  332. //-----------------------------------------------------------------------------
  333. D3DDISPLAYMODE *DeviceEnumeration::GetSelectedDisplayMode()
  334. {
  335.     return &m_selectedDisplayMode;
  336. }
  337.  
  338. //-----------------------------------------------------------------------------
  339. // Indicates if the display is windowed or fulscreen.
  340. //-----------------------------------------------------------------------------
  341. bool DeviceEnumeration::IsWindowed()
  342. {
  343.     return m_windowed;
  344. }
  345.  
  346. //-----------------------------------------------------------------------------
  347. // Indicates if the display is v-synced.
  348. //-----------------------------------------------------------------------------
  349. bool DeviceEnumeration::IsVSynced()
  350. {
  351.     return m_vsync;
  352. }
  353.  
  354. //-----------------------------------------------------------------------------
  355. // Adds an entry to the combo box.
  356. //-----------------------------------------------------------------------------
  357. void DeviceEnumeration::ComboBoxAdd( HWND dialog, int id, void *data, char *desc )
  358. {
  359.     HWND control = GetDlgItem( dialog, id );
  360.     int i = ComboBox_AddString( control, desc );
  361.     ComboBox_SetItemData( control, i, data );
  362. }
  363.  
  364. //-----------------------------------------------------------------------------
  365. // Selects an entry in the combo box by index.
  366. //-----------------------------------------------------------------------------
  367. void DeviceEnumeration::ComboBoxSelect( HWND dialog, int id, int index )
  368. {
  369.     HWND control = GetDlgItem( dialog, id );
  370.     ComboBox_SetCurSel( control, index );
  371.     PostMessage( dialog, WM_COMMAND, MAKEWPARAM( id, CBN_SELCHANGE ), (LPARAM)control );
  372. }
  373.  
  374. //-----------------------------------------------------------------------------
  375. // Selects an entry in the combo box by data.
  376. //-----------------------------------------------------------------------------
  377. void DeviceEnumeration::ComboBoxSelect( HWND dialog, int id, void *data )
  378. {
  379.     HWND control = GetDlgItem( dialog, id );
  380.     for( int i = 0; i < ComboBoxCount( dialog, id ); i++ )
  381.     {
  382.         if( (void*)ComboBox_GetItemData( control, i ) == data )
  383.         {
  384.             ComboBox_SetCurSel( control, i );
  385.             PostMessage( dialog, WM_COMMAND, MAKEWPARAM( id, CBN_SELCHANGE ), (LPARAM)control );
  386.             return;
  387.         }
  388.     }
  389. }
  390.  
  391. //-----------------------------------------------------------------------------
  392. // Returns the data for the selected entry in the combo box.
  393. //-----------------------------------------------------------------------------
  394. void *DeviceEnumeration::ComboBoxSelected( HWND dialog, int id )
  395. {
  396.     HWND control = GetDlgItem( dialog, id );
  397.     int index = ComboBox_GetCurSel( control );
  398.     if( index < 0 )
  399.         return NULL;
  400.     return (void*)ComboBox_GetItemData( control, index );
  401. }
  402.  
  403. //-----------------------------------------------------------------------------
  404. // Checks if a valid entry in the combo box is selected.
  405. //-----------------------------------------------------------------------------
  406. bool DeviceEnumeration::ComboBoxSomethingSelected( HWND dialog, int id )
  407. {
  408.     HWND control = GetDlgItem( dialog, id );
  409.     int index = ComboBox_GetCurSel( control );
  410.     return ( index >= 0 );
  411. }
  412.  
  413. //-----------------------------------------------------------------------------
  414. // Returns the number of entries in the combo box.
  415. //-----------------------------------------------------------------------------
  416. int DeviceEnumeration::ComboBoxCount( HWND dialog, int id )
  417. {
  418.     HWND control = GetDlgItem( dialog, id );
  419.     return ComboBox_GetCount( control );
  420. }
  421.  
  422. //-----------------------------------------------------------------------------
  423. // Checks if the combo box contains the given text.
  424. //-----------------------------------------------------------------------------
  425. bool DeviceEnumeration::ComboBoxContainsText( HWND dialog, int id, char *text )
  426. {
  427.     char item[MAX_PATH];
  428.     HWND control = GetDlgItem( dialog, id );
  429.     for( int i = 0; i < ComboBoxCount( dialog, id ); i++ )
  430.     {
  431.         ComboBox_GetLBText( control, i, item );
  432.         if( lstrcmp( item, text ) == 0 )
  433.             return true;
  434.     }
  435.     return false;
  436. }